﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Conventions;
using MovieDB.Data.Configs;
using MovieDB.Data.Entities;
using NHibernate;
using NHibernate.ByteCode.Castle;
using NHibernate.Cfg;
using ForeignKeyConvention = MovieDB.Data.Configs.ForeignKeyConvention;

namespace MovieDB.Data.Repositories
{
    public class SessionProvider
    {
        private const string MappingConfigsResourcePath = ".Configs.";
        private const string MappingConfigsExtension = ".hbm.xml";
        private static ISessionFactory _sessionFactory = null;

        //public static ISessionFactory SessionFactory
        //{
        //    get
        //    {
        //        if (_sessionFactory == null)
        //        {
        //            var cfg = new Configuration();
        //            cfg.Configure();
        //            LoadConfigsInAssemblyResources(cfg);
        //            _sessionFactory = cfg.BuildSessionFactory();
        //        }
        //        return _sessionFactory;
        //    }
        //}

        //private static void LoadConfigsInAssemblyResources(Configuration cfg)
        //{
        //    Type type = typeof(IRepository<>);
        //    Assembly assembly = type.Assembly;
        //    string[] embededResourceNames = assembly.GetManifestResourceNames();
        //    embededResourceNames = embededResourceNames.Where(
        //        x => x.Contains(MappingConfigsResourcePath) && x.EndsWith(MappingConfigsExtension)).ToArray();
        //    foreach (var embededResourceName in embededResourceNames)
        //    {
        //        using (Stream stream = assembly.GetManifestResourceStream(embededResourceName))
        //        {
        //            using (var reader = new StreamReader(stream))
        //            {
        //                string xml = reader.ReadToEnd();
        //                cfg.AddXmlString(xml);
        //            }
        //        }
        //    }
        //}

        public static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
                    var factory = Fluently.Configure()
                        .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("MovieDB"))
                            .ProxyFactoryFactory(typeof(ProxyFactoryFactory)))
                        .Mappings(GetMappings)
                        .BuildSessionFactory();

                    _sessionFactory = factory;
                }

                return _sessionFactory;
            }
        }

        private static void GetMappings(MappingConfiguration mappingConfig)
        {
            var mappings = AutoMap.Source(new EntitiesToMapSource(), new AutoMapConfiguration())
                .Conventions.Add(GetConventions());

            mappingConfig.AutoMappings.Add(mappings);
            mappingConfig.AutoMappings.ExportTo(@"D:\temp\movieDB_map");
        }

        private static IConvention[] GetConventions()
        {
            return new IConvention[]
                       {
                           new ForeignKeyConvention(),
                           new VersionConvention(),
                           new ClassMapConvention(),
                           new ManyToManyConvention()
                       };
        }
    }
}
